home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 22 code / Paper Juggling / PaperJuggling.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-19  |  12.5 KB  |  348 lines  |  [TEXT/MMCC]

  1. /*
  2.     Paper Juggling, written by Dave Johnson
  3.     
  4.     
  5.     This program implements a sort of "active graph paper" for messing with
  6.     multi-person juggling patterns. See The Veteran Neophyte in develop
  7.     magazine issue 22 for an explanation of juggling patterns in general and
  8.     this notation in particular. Keep reading for implementation details.
  9.     
  10.     This program is hacked together for fun, and should not be considered a good
  11.     example of anything.
  12.     
  13.     -----------------------------------------
  14.     !! Use at your own (considerable) risk !!
  15.     -----------------------------------------
  16.     
  17.     •GX Strategy:
  18.     
  19.     A lot of the general-purpose GX-specific code (printing, etc.) is stolen directly
  20.     from the GXShell sample by Dave Hersey and Pete "Luke" Alexander.
  21.     
  22.     There are four picture objects that contain all the application-specific 
  23.     graphical objects:
  24.     -One contains the dashed separator lines.
  25.     -Another contains each of the jugglers in the pattern (each juggler is in turn
  26.     a picture containing several "hands," which are just "L" or "R" text shapes).
  27.     -Another contains all the primary throws (arrows).
  28.     -The last one contains all the "faded" throws.
  29.     
  30.     There is one more picture object that contains the separatorsm jugglers, and 
  31.     primary throws, used mostly for printing and for one-step drawing during updates.
  32.     
  33.     The throw shapes use an ink that draws in xor mode, this is handy for fast erasing
  34.     and redrawing without disturbing underlying bits. (Thank goodness for the transfer
  35.     mode library and the SetInkFastXorTransfer routine.) Unfortunately that routine
  36.     works on only one device at a time (see Known Deficiencies below).
  37.     
  38.     The faded throw shapes are drawn simultaneously into two separate viewports, which
  39.     is how the ones that "wrap" are drawn in two places at once while dragging. Spiffy.
  40.     
  41.     Many more piddling details are discussed in the declarations below and in the code
  42.     itself.
  43.     
  44.     •Known Deficiencies:
  45.     
  46.     Printing isn't great, though it's there. The problem is that the faded throws don't
  47.     print, since they're drawn into different viewports.
  48.     
  49.     Multiple Monitor support is non-existent. This wouldn't be too hard to fix: make a 
  50.     separate ink for each monitor, and use DeviceLoop to figure out which one to use on
  51.     the fly.
  52.  
  53.     •Known Bugs:
  54.     
  55.     Too many to tell you about them all... :-)
  56.  
  57. */
  58.  
  59. #include "Shell.h"
  60. //  #include "AppInterface.h"
  61.  
  62.  
  63.  
  64. //------------------------------
  65. // Constants
  66.  
  67. // Colors
  68. #define    kBGColor            white
  69. #define kSeparatorColor        black
  70. #define kArrowColor            red
  71. #define kHandColor            blue
  72. #define kLabelColor            black
  73.  
  74. // Distances and other constant numbers
  75. #define kArrowHeadLength    ff(4)
  76. #define kArrowHeadHeight    ff(4)
  77. #define kArrowPenSize        ff(3)
  78.  
  79. #define kDefaultGridSpace    ff(48)    // Grid spacing
  80. #define kDefaultJugglers    2        // Number of jugglers
  81. #define kDefaultCounts        6        // Number of time steps (hands per juggler)
  82. #define kMaxJugglers        20        // Maximum number of jugglers
  83. #define kMaxCounts            72        // Maximum number of counts (arbitrary, really, but any more would be unreasonable :-)
  84. #define kNumVSeparators        3        // number of vertical separators
  85. #define kHandTextSize        (ff(16))
  86. #define kLabelTextSize        (ff(9))    
  87. #define kThrowDetent        (ff(18))    // distance from which a throw "leaps" to the hand
  88. #define kHandRadius            (ff(8))        // The distance a point can be away from the center of a hand
  89.                                         // and still be considered inside it, used for fast hit testing
  90.                                         // and for offsetting a throw's coords
  91.     
  92.  
  93. // Resources
  94. #define kThumbCursorID        128
  95. // #define kTimeSlipCursorID    129 // Someday I'll use this
  96.  
  97. // File constants
  98. #define kJuggleFileType        'JUGL'
  99. #define kJuggleCreatorType    'JUGL'
  100.  
  101. // Dialog resource ids and item numbers
  102. #define kJuggleSizeDialogId     130
  103. //#define     iOKButton             1    // these are already defined in DialogUtils.h
  104. //#define     iCancelButton         2
  105. //#define     iOutline             3
  106. #define     iNumJugglers         4 // The number of jugglers text item
  107. #define     iNumCounts             5 // The number of counts text item
  108.     
  109. // Menus and menu items
  110. #define kNumAppMenus            1
  111.  
  112. #define    kJuggleMenuID            131
  113. #define     iResizeJuggle        1
  114. #define     iAddJuggler            2
  115.  
  116. // location in the global menu handle array
  117. #define    kJuggleMenu                0
  118.  
  119.  
  120. //------------------------------
  121. // Macros
  122.  
  123. #define    fixAbs(a) ((a < 0) ? -a : a)
  124.  
  125. //-------------------------------
  126. // Types
  127.  
  128. // A HandLoc is much like a point, and specifies a particular hand location in the 
  129. // array in memory.
  130. // (Note that this does not necessarily correspond to any particular position on  
  131. // screen, since jugglers can be rearranged - i.e. juggler 1 may be three rows down)
  132. // Values are always positive (1-based) - zero signifies "none"
  133. typedef struct HandLoc
  134. {
  135.     short    time;
  136.     short    juggler;
  137. }HandLoc, *HandLocPtr;
  138.  
  139. // A Hand is just a pair of HandLocs, specifying the source and sink for the hand.
  140. // In a "complete" pattern, every hand must have BOTH a source and a sink
  141. typedef struct Hand
  142. {
  143.     HandLoc    source;
  144.     HandLoc    sink;
  145. } Hand, *HandPtr, **HandHandle;
  146.  
  147. /* This structure represents each "document". The FSSpec is used to keep track of whether
  148.     a Save command should call Save As, and if not which file to save into. The dirty
  149.     flag is used to keep track of when saving is necessary. The scroll bars are the scroll
  150.     bars. the contentSize is the size of the document, in pixels. The Juggle stuff is the 
  151.     juggle stuff. */
  152. typedef struct
  153. {
  154.     // Standard shell stuff
  155.     Point            contentSize;
  156.     ControlHandle    hScroll;
  157.     ControlHandle    vScroll;
  158.     FSSpec            fileSpec;
  159.     Boolean            dirty;
  160.     
  161.     // Standard GX stuff
  162.     gxJob            docJob;            // print job for this document.
  163.     gxShape            docPage;        // page shape description.
  164.     gxViewPort        docPort;        // The child of the window's view port, used for scrolling
  165.     
  166.     // The Juggle
  167.     
  168.     // ----• Graphics stuff •----
  169.  
  170.     // The faded view ports
  171.     gxViewPort    afterPort;         // the view port for drawing ghost throws to the right
  172.                                 // of the main hands
  173.     gxViewPort    beforePort;     // the view port for drawing ghost throws that come in
  174.                                 // from the left to the main hands.
  175.  
  176.     // The shapes
  177.     gxShape     jugglersPict;    // picture containing the jugglers
  178.     gxShape        throwsPict;        // picture containing all the throws (arrows)
  179.     gxShape        fadedThrowsPict;// picture containing all the ghost throws
  180.     gxShape        sepsPict;        // picture containing all the separator lines in the juggle
  181.  
  182.     // ----• Non-graphics stuff •----
  183.     
  184.     // An array of shorts used to map position on screen to the actual juggler row in memory.
  185.     // Position in the array corresponds to position on screen, the value of an array slot
  186.     // is the row of the juggler occupying that position on screen.
  187.     short         jugglerMap[kMaxJugglers];
  188.  
  189.     
  190.     // State variables
  191.     gxPoint        gridPt;            // The grid spacing in 72nds of an inch
  192.     short        numJugglers;    // number of jugglers (rows)
  193.     short        numCounts;        // number of time steps (columns)
  194.     
  195.     // The connections data is a 2D array of hands. How big the array is
  196.     // will vary depending on the number of jugglers and the number of time
  197.     // steps. How the hands are linked up (the pattern itself) 
  198.     // is determined by the data in the Hands.
  199.     HandHandle        theThrows;
  200.     
  201. }DocumentRecord, *DocPeek, **DocHandle, Juggle, *JugglePointer, **JuggleHandle;
  202.  
  203.  
  204. //------------------------------
  205. // Prototypes
  206.  
  207. // ----• JuggleRoutines.c •----
  208.  
  209. // Init and CleanUp
  210. OSErr                InitJuggle(WindowPtr wind, short numJugglers, short numCounts);
  211. void                CleanUpJuggle(WindowPtr window, Boolean graphicsToo);
  212.  
  213. // accessor routines for the juggle stuff in the window
  214. DocHandle            GetWindowDoc(WindowPtr wind);
  215. JuggleHandle        GetWindowJuggle(WindowPtr wind);
  216.  
  217. // throw manipulation routines
  218. Boolean             ResizeThrows(JuggleHandle aJuggle, short numJugglers, short numCounts,
  219.                                         Boolean copyThrows);
  220. HandPtr                GetHandPtr(HandHandle throws, short numCounts, short juggler, short count);
  221. HandPtr                GetHand(JuggleHandle aJuggle, HandLoc theLoc, Boolean wrapIt);
  222. HandPtr                GetIndexedHand(JuggleHandle aJuggle, short time, short juggler,
  223.                                     Boolean wrapIt);
  224.  
  225. void                AddThrow(JuggleHandle aJuggle, HandLoc from, HandLoc to);
  226. void                AddIndexedThrow(JuggleHandle aJuggle,
  227.                         short fromTime, short fromJuggler,
  228.                         short toTime, short toJuggler    );
  229.  
  230. void                RemoveThrow(JuggleHandle aJuggle, HandLoc from, HandLoc to);
  231. void                RemoveIndexedThrow(JuggleHandle aJuggle,
  232.                         short fromTime, short fromJuggler,
  233.                         short toTime, short toJuggler    );
  234.  
  235. void                ClearJugglerThrows(JuggleHandle aJuggle, short juggler);
  236. void                 CopyThrows(HandHandle oldThrows, short oldJugglers, short oldCounts,
  237.                                 HandHandle newThrows, short newJugglers, short newCounts);
  238. HandLoc                FindReceiver(JuggleHandle aJuggle, HandLoc    from);
  239.  
  240. // routines that handle jugglers
  241. void                MoveJuggler(JuggleHandle aJuggle, short whichJuggler, short offset);
  242. Boolean                AddJuggler(JuggleHandle aJuggle);
  243. WindowPtr            ResizeJuggle(WindowPtr wind);
  244.  
  245.  
  246. // ----• JuggleGraphics.c •----
  247.  
  248. // initialization and clean up
  249. void                InitCommonGraphicObjects(void);
  250. void                KillCommonGraphicObjects(void);
  251.  
  252. // shape creation
  253. gxShape                MakeThrowShape(JuggleHandle aJuggle, Boolean faded);
  254. gxShape                MakeHandShape(Boolean rightHand, Boolean faded);
  255. gxShape                MakeLabelShape(short jugglerNumber);
  256. gxShape                MakeSeparatorShape(JuggleHandle aJuggle, Boolean isHoriz);
  257. gxShape             MakeJugglerShape(JuggleHandle aJuggle, Boolean rightFirst, short jugglerNumber);
  258. gxShape                MakePrintingShape(JuggleHandle aJuggle);
  259. OSErr                SetUpJuggleViewPorts(WindowPtr window, JuggleHandle aJuggle);
  260. gxShape                SetUpJuggleGraphics(WindowPtr window, JuggleHandle aJuggle);
  261. void                CleanUpJuggleShapes(WindowPtr window);
  262.  
  263. // Graphics utilities
  264. void                AddNewThrowShape(JuggleHandle aJuggle, gxLine *line, Boolean draw);
  265. void                RemoveThrowShape(JuggleHandle aJuggle, short index);
  266. void                MoveThrowShape(JuggleHandle aJuggle, short shapeIndex, gxLine *newLine);
  267. void                RebuildThrowsPict(JuggleHandle aJuggle);
  268.  
  269. void                MoveJugglerInPict(JuggleHandle aJuggle, short fromRow, short toRow);
  270. void                SwitchJugglerHands(JuggleHandle aJuggle, short index);
  271. void                ChangeJugglerLabel(JuggleHandle aJuggle, short juggler, short newId);
  272.  
  273. void                SetDeepShapeInk(gxShape sh, gxInk ink);
  274. RgnHandle            GetShapeBoundsRgn(gxShape juggler);
  275. Rect*                GetShapeBoundsQDRect(gxShape shape, Rect *rect);
  276. Point                GetQDWindowOrigin(WindowPtr window);
  277.  
  278. void                SetShapeFadePorts(JuggleHandle aJuggle, gxShape shape);
  279. void                SetShapeMainPort(JuggleHandle aJuggle, gxShape shape);
  280. void                SetInkBlendMode(gxInk theInk, short percent);
  281.  
  282. void                ResetJuggleContentSize(JuggleHandle aJuggle);
  283.  
  284. // Accessors
  285. gxShape                GetDocThrowsPict(WindowPtr wind);
  286. gxShape                GetDocFadedThrowsPict(WindowPtr wind);
  287.  
  288. // ----• JuggleInterface.c •----
  289.  
  290. // mouse handling routines
  291. void                DoJuggleClick(WindowPtr window, Point p, EventRecord *event);
  292. void                DragJuggler(WindowPtr window, gxShape jugglerPict, gxPoint *clickPt,
  293.                                     short whichJuggler, short constraint);
  294. void                 DragNewThrow(WindowPtr window, gxPoint *from);
  295. void                DragThrow(    JuggleHandle aJuggle,
  296.                                 long    shapeIndex,
  297.                                 long     whichPoint,
  298.                                 gxPoint *from    );
  299. Point                DragGrayRgnGridded(    RgnHandle theRgn,
  300.                                         Point startPt,
  301.                                         Rect *limitRect,
  302.                                         Rect *slopRect,
  303.                                         short axis,
  304.                                         Point grid,
  305.                                         Point *initialOffset);
  306. void                KeepPtInBounds(JuggleHandle aJuggle, gxPoint *goodPt);
  307.  
  308. // grid enforcement
  309. void                GetGridOffset(gxPoint *pointData, gxPoint *grid);
  310. void                GetShortGridOffset(Point *pointData, Point grid);
  311. Boolean             Detent(gxPoint *pointData, gxPoint *grid, Fixed detentLimit);
  312. void                SetGridPos(gxPoint *pointData, gxPoint *grid);
  313.  
  314. // Screen conversion routines
  315. void                MoveJugglerInMap(JuggleHandle aJuggle, short whichJuggler,
  316.                                             short fromRow, short toRow);
  317. short                JugglerToRow(JuggleHandle aJuggle, short juggler);
  318. short                RowToJuggler(JuggleHandle aJuggle, short row);
  319. void                HandLocToPoint(JuggleHandle aJuggle, HandLoc *hand, gxPoint *point);
  320. void                PointToHandLoc(JuggleHandle aJuggle, gxPoint *point, HandLoc *hand,
  321.                                     Boolean wrapIt);
  322. HandPtr                PointToHand(JuggleHandle aJuggle, gxPoint *point, Boolean wrapIt);
  323.  
  324. void                LineToAddedThrow(JuggleHandle aJuggle, gxLine *line);
  325. void                LineToRemovedThrow(JuggleHandle aJuggle, gxLine *line);
  326.  
  327. // Dialog routines
  328. void                DoJuggleSizeDialog(short *numCounts, short *numJugglers);
  329. Boolean                JuggleSizeOK(DialogPtr dptr);
  330.  
  331.  
  332. // String utility routines, from DTS
  333. short                clen(char *cptr);
  334. char*                ccat(char *s1, char *s2);
  335. char*                ccpy(char *s1, char *s2);
  336. void                p2c(StringPtr cptr);
  337.  
  338. // utils
  339. short                min(short a, short b);
  340.  
  341. // ----• JuggleFiles.c •----
  342. OSErr                SaveJuggle(JuggleHandle aJuggle);
  343. OSErr                JuggleToExistingFile(FSSpec *fileSpec, JuggleHandle aJuggle);
  344. OSErr                JuggleToNewFile(FSSpec *fileSpec, JuggleHandle aJuggle);
  345. OSErr                WriteJuggleToFile(FSSpec *fileSpec, JuggleHandle aJuggle);
  346. OSErr                OpenJuggleFile(FSSpec *fileSpec, WindowPtr *wind);
  347.  
  348.